﻿using System;
using System.Collections.ObjectModel;
using Navigant.Infrastructure.Cases;
using Navigant.Infrastructure.DomainBase;
using Navigant.Model.Cases;
using Navigant.Model.Custodians;
using System.Collections.Generic;

namespace Navigant.Model.PreservationNotices
{
    public class PreservationNotice : CaseChildItem, IAggregateRoot
    {
        private int custodianId;
        private Custodian to;
        private string fromAddress;
        private string subject;
        private string body;
        private string messageIdentifier;
        private int templateId;
        private string templateName;
        private PreservationNoticeTemplate template;
        private PreservationNoticeStatus status;
        private DateTime dateMessageCreated;
        private DateTime? dateMessageSent;
        private DateTime? dateMessageAcknowledged;
        private int smtpVerificationTries;
        private List<Attachment> attachments;

        public PreservationNotice(ICase parentCase, int custodianId,
            string fromAddress, string subject, string body,
            string messageIdentifier, int templateId, string templateName,
            DateTime dateMessageCreated)
            : this(0, parentCase, null, fromAddress, subject, body, messageIdentifier,
            null, PreservationNoticeStatus.Unsent, dateMessageCreated, null, null, 0)
        {
            this.templateId = templateId;
            this.templateName = templateName;
            this.custodianId = custodianId;
        }

        public PreservationNotice(ICase parentCase,
            Custodian to, string fromAddress, string subject, string body, 
            string messageIdentifier, PreservationNoticeTemplate template, 
            DateTime dateMessageCreated)
            : this(0, parentCase, to, fromAddress, subject, body, messageIdentifier,
            template, PreservationNoticeStatus.Unsent, dateMessageCreated, null, 
            null, 0)
        {
        }

        public PreservationNotice(int id, ICase parentCase,
            int custodianId, string fromAddress, string subject, string body,
            string messageIdentifier, int templateId, string templateName,
            PreservationNoticeStatus status, DateTime dateMessageCreated, 
            DateTime? dateMessageSent, DateTime? dateMessageAcknowledged,
            int smtpVerificationTries)
            : this(id, parentCase, null, fromAddress, subject, body, 
            messageIdentifier, null, status, dateMessageCreated, 
            dateMessageSent, dateMessageAcknowledged, smtpVerificationTries)
        {           
            this.custodianId = custodianId;
            this.templateId = templateId;
            this.templateName = templateName;
        }

        public PreservationNotice(int id, ICase parentCase,
            Custodian to, string fromAddress, string subject, string body, 
            string messageIdentifier, PreservationNoticeTemplate template, 
            PreservationNoticeStatus status, DateTime dateMessageCreated, 
            DateTime? dateMessageSent, DateTime? dateMessageAcknowledged,
            int smtpVerificationTries) 
            : base(id, parentCase)
        {
            this.to = to;
            if (this.to != null && this.custodianId == 0)
            {
                this.custodianId = this.to.Id;
            }
            this.fromAddress = fromAddress;
            this.subject = subject;
            this.body = body;
            this.messageIdentifier = messageIdentifier;
            this.template = template;
            if (this.template != null)
            {
                if (this.TemplateId == 0)
                {
                    this.templateId = this.template.Id;
                }
                if (string.IsNullOrEmpty(this.templateName))
                {
                    this.templateName = this.template.Name;
                }
            }
            this.status = status;
            this.dateMessageCreated = dateMessageCreated;
            this.dateMessageSent = dateMessageSent;
            this.dateMessageAcknowledged = dateMessageAcknowledged;
            this.smtpVerificationTries = smtpVerificationTries;
        }

        public Custodian To
        {
            get 
            {
                if (this.to == null && this.custodianId > 0)
                {
                    CustodianService service = new CustodianService(this.ParentCase, null, true);
                    this.to = service.GetCustodian(this.custodianId);
                }
                return this.to; 
            }
        }

        public string FromAddress
        {
            get { return this.fromAddress; }
        }

        public string Subject
        {
            get { return this.subject; }
        }

        public string Body
        {
            get { return this.body; }
        }

        public string MessageIdentifier
        {
            get { return this.messageIdentifier; }
        }

        public int TemplateId
        {
            get 
            {
                int id = this.templateId;
                if (id < 1 && this.Template != null)
                {
                    id = this.Template.Id;
                }
                return id;
            }
        }

        public string TemplateName
        {
            get
            {
                string templateName = this.templateName;
                if (string.IsNullOrEmpty(templateName) && this.Template != null)
                {
                    templateName = this.Template.Name;
                }
                return templateName;
            }
        }

        public PreservationNoticeTemplate Template
        {
            get 
            {
                if (this.template == null && this.templateId > 0)
                {
                    PreservationNoticeTemplateService service = new PreservationNoticeTemplateService(this.ParentCase, null, true);
                    this.template = service.GetPreservationNoticeTemplate(this.templateId);
                }
                return this.template; 
            }
        }

        public ReadOnlyCollection<Attachment> Attachments
        {
            get 
            {
                if (this.attachments == null)
                {
                    // Existing notice
                    if (this.Id > 0)
                    {
                        PreservationNoticeService service = new PreservationNoticeService(this.ParentCase, null, true);
                        this.attachments = new List<Attachment>(service.FindAttachments(this.Id));
                    }
                    else
                    {
                        // A new notice
                        this.attachments = new List<Attachment>();
                        foreach (Attachment attachment in this.Template.Attachments)
                        {
                            this.attachments.Add(attachment);
                        }                        
                    }
                }
                return this.attachments.AsReadOnly(); 
            }
        }

        public ReadOnlyCollection<HtmlImageData> Images
        {
            get { return this.Template.Images; }
        } 

        public PreservationNoticeStatus Status
        {
            get { return this.status; }
            set { this.status = value; }
        }

        public DateTime DateMessageCreated
        {
            get { return this.dateMessageCreated; }
        }

        public DateTime? DateMessageSent
        {
            get { return this.dateMessageSent; }
        }

        public DateTime? DateMessageAcknowledged
        {
            get { return this.dateMessageAcknowledged; }
        }

        public int SmtpVerificationTries
        {
            get { return this.smtpVerificationTries; }
        }

        public void MessageNotVerified()
        {
            this.smtpVerificationTries++;
        }

        public void MessageSent(bool reminder)
        {
            if (reminder)
            {
                this.status = PreservationNoticeStatus.ReminderQueued;
            }
            else
            {
                this.status = PreservationNoticeStatus.NoticeQueued;
            }
        }

        public void MessageVerifiedSent(DateTime dateMessageSent)
        {
            // The datetime that the message was sent cannot be before
            // the message was created
            if (dateMessageSent < this.DateMessageCreated)
            {
                this.dateMessageSent = this.DateMessageCreated;
            }
            else
            {
                this.dateMessageSent = dateMessageSent;
            }
            if (this.status == PreservationNoticeStatus.ReminderQueued)
            {
                this.status = PreservationNoticeStatus.Reminded;
            }
            else
            {
                this.status = PreservationNoticeStatus.Sent;
            }
        }

        public void Acknowledge()
        {
            this.status = PreservationNoticeStatus.Acknowledged;
            this.dateMessageAcknowledged = DateTime.Now;
            if (this.To != null)
            {
                this.To.NoticeAcknowledged(this.dateMessageAcknowledged.Value);
            }

            // If the message was acknowledged, and the message 
            // has not been verified as sent yet, then set the 
            // dateMessageSent value to the date it was first created
            // An acknowledgement always trumps the smtp verification.
            if (!this.dateMessageSent.HasValue)
            {
                this.dateMessageSent = this.dateMessageCreated;
                // Updated the associated Custodian also
                if (this.To != null)
                {
                    this.To.NoticeVerifiedSent(this.dateMessageCreated, false);
                }
            }
        }
        
        protected override void Validate()
        {
        }

        protected override BrokenRuleMessages GetBrokenRuleMessages()
        {
            return null;
        }

        protected override void LoadExtendedProperties()
        {
        }
    }
}
